/*
 *  Copyright (C) 2012 Компания ВИТ. web: http://diasled.ru Е-mail:  vit@diasled.ru
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package ru.apertum.diasled.forms;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.util.Date;
import java.util.GregorianCalendar;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import org.jdesktop.application.Action;
import ru.apertum.diasled.common.Uses;
import ru.apertum.diasled.common.Uses.ClientException;
import ru.apertum.diasled.model.Examination;
import ru.apertum.diasled.model.Visit;
import ru.apertum.diasled.model.exam.ExamNode;
import ru.apertum.diasled.model.exam.ExamTree;
import ru.apertum.diasled.model.exam.RootNodeExam;
import ru.apertum.diasled.model.patients.VisitsTableModel;

/**
 * Форма отображения информации по конкретному посещению.
 * Имеет возможность переключения на следующее/предыдущее посещение или на произвольное.
 * @author Evgeniy Egorov, Aperum Projects
 */
public class FVisitEditor extends javax.swing.JFrame {

    private Visit visit = null;

    /**
     * 
     * @param patient не null
     * @param visit не null
     * @param tModel модель для таблици посещений
     */
    public FVisitEditor(Visit visit, TableModel tModel) {
        initComponents();
        // свернем по esc
        getRootPane().registerKeyboardAction(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (isChangedVisit() && JOptionPane.showConfirmDialog(null,
                        "Данные по посещению были изменены. Сохранить изменения?",
                        "Сохранение посещения",
                        JOptionPane.YES_NO_OPTION) == 0) {
                    saveVisit();
                } else {
                    setVisible(false);
                }
            }
        },
                KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
                JComponent.WHEN_IN_FOCUSED_WINDOW);
        try {
            setIconImage(ImageIO.read(DiasledView.class.getResource("/ru/apertum/diasled/forms/resources/favicon.png")));
        } catch (IOException ex) {
            System.err.println(ex);
        }

        tablePatientVisits.setModel(tModel);
        tablePatientVisits.getSelectionModel().addListSelectionListener(new ListSelectionListener() {

            @Override
            public void valueChanged(ListSelectionEvent e) {
                if (tablePatientVisits.getModel().getRowCount() != 0 && e.getFirstIndex() >= 0 && e.getLastIndex() >= 0 && tablePatientVisits.getSelectedRow() >= 0) {
                    final Date date = (Date) tablePatientVisits.getModel().getValueAt(tablePatientVisits.getSelectedRow(), 1);
                    final Visit v = ((VisitsTableModel) tablePatientVisits.getModel()).getVisitByDate(date);
                    showData(v);
                }
            }
        });
        selectByVisit(visit);
    }

    /**
     * Показываем инфу о визите, выставляем текущий отображаемый визит
     * @param patient
     * @param visit 
     */
    private void showData(Visit visit) {
        if (this.visit != null && isChangedVisit() && JOptionPane.showConfirmDialog(this,
                "Данные по посещению были изменены. Сохранить изменения?",
                "Сохранение посещения",
                JOptionPane.YES_NO_OPTION) == 0) {
            saveVisit();
            return;
        }
        this.visit = visit;
        final boolean isNow = Uses.isNow(visit.getDate());
        labelPatientInfo.setText("<html>" + visit.getPatient().getTextInfo());
        textFieldVisitDescription.setText(visit.getComments());
        labelVisitDate.setText("Дата посещения " + Uses.format_dd_MM_yyyy.format(visit.getDate()));
        final GregorianCalendar gc = new GregorianCalendar();
        gc.setTime(visit.getPatient().getBirthday());
        labelAgeOnDate.setText("Полных лет на дату посещения " + visit.getPatient().getAgeOnDate(visit.getDate()));
        textFieldKod.setText(visit.getKod());
        spinnerWeightOnData.getModel().setValue(visit.getWeight());
        textAreaCommonStatus.setText(visit.getCommonStatus());
        textAreaLeftLeg.setText(visit.getLeftLegInfo());
        textAreaRightLeg.setText(visit.getRigthLegInfo());
        if (isNow) {
            // сегодняшнее посещение, новое
        } else {
            // смотрим старое посещение
        }
        textFieldVisitDescription.setEditable(isNow);
        spinnerWeightOnData.setEnabled(isNow);
        textFieldKod.setEditable(isNow);
        textAreaCommonStatus.setEditable(isNow);
        textAreaLeftLeg.setEditable(isNow);
        textAreaRightLeg.setEditable(isNow);

        treeExams.setModel(new ExamTree(visit));

        org.jdesktop.application.Application.getInstance(ru.apertum.diasled.Diasled.class).getContext().getActionMap(FVisitEditor.class, this).get("saveVisit").setEnabled(isNow);

        org.jdesktop.application.Application.getInstance(ru.apertum.diasled.Diasled.class).getContext().getActionMap(FVisitEditor.class, this).get("createNewExam").setEnabled(isNow);
        org.jdesktop.application.Application.getInstance(ru.apertum.diasled.Diasled.class).getContext().getActionMap(FVisitEditor.class, this).get("removeExam").setEnabled(isNow);

        buttonNextVisit.setEnabled(getVisitCloseOf(visit, true) != null);
        buttonPreviousVisit.setEnabled(getVisitCloseOf(visit, false) != null);


    }

    private boolean isChangedVisit() {
        final boolean isNow = Uses.isNow(visit.getDate());
        return isNow
                && !(visit.getComments().equals(textFieldVisitDescription.getText())
                && visit.getKod().equals(textFieldKod.getText())
                && visit.getWeight().equals(spinnerWeightOnData.getModel().getValue())
                && visit.getCommonStatus().equals(textAreaCommonStatus.getText())
                && visit.getLeftLegInfo().equals(textAreaLeftLeg.getText())
                && visit.getRigthLegInfo().equals(textAreaRightLeg.getText()));
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jSplitPane1 = new javax.swing.JSplitPane();
        jPanel1 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        labelPatientInfo = new javax.swing.JLabel();
        jPanel2 = new javax.swing.JPanel();
        buttonSave = new javax.swing.JButton();
        jScrollPane2 = new javax.swing.JScrollPane();
        tablePatientVisits = new javax.swing.JTable();
        jPanel3 = new javax.swing.JPanel();
        jPanel4 = new javax.swing.JPanel();
        labelAgeOnDate = new javax.swing.JLabel();
        spinnerWeightOnData = new javax.swing.JSpinner();
        jLabel3 = new javax.swing.JLabel();
        labelVisitDate = new javax.swing.JLabel();
        textFieldKod = new javax.swing.JTextField();
        jLabel5 = new javax.swing.JLabel();
        textFieldVisitDescription = new javax.swing.JTextField();
        jLabel6 = new javax.swing.JLabel();
        jPanel5 = new javax.swing.JPanel();
        buttonNextVisit = new javax.swing.JButton();
        buttonPreviousVisit = new javax.swing.JButton();
        jTabbedPane1 = new javax.swing.JTabbedPane();
        jPanel6 = new javax.swing.JPanel();
        jSplitPane2 = new javax.swing.JSplitPane();
        jSplitPane3 = new javax.swing.JSplitPane();
        jScrollPane4 = new javax.swing.JScrollPane();
        textAreaLeftLeg = new javax.swing.JTextArea();
        jScrollPane5 = new javax.swing.JScrollPane();
        textAreaRightLeg = new javax.swing.JTextArea();
        jScrollPane3 = new javax.swing.JScrollPane();
        textAreaCommonStatus = new javax.swing.JTextArea();
        jPanel7 = new javax.swing.JPanel();
        jPanel8 = new javax.swing.JPanel();
        buttonAddExam = new javax.swing.JButton();
        buttonRemoveExam = new javax.swing.JButton();
        jButton1 = new javax.swing.JButton();
        jScrollPane6 = new javax.swing.JScrollPane();
        treeExams = new javax.swing.JTree();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(ru.apertum.diasled.Diasled.class).getContext().getResourceMap(FVisitEditor.class);
        setTitle(resourceMap.getString("Form.title")); // NOI18N
        setName("Form"); // NOI18N
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        jSplitPane1.setDividerLocation(505);
        jSplitPane1.setDividerSize(7);
        jSplitPane1.setContinuousLayout(true);
        jSplitPane1.setName("jSplitPane1"); // NOI18N

        jPanel1.setName("jPanel1"); // NOI18N

        jScrollPane1.setBorder(new javax.swing.border.MatteBorder(null));
        jScrollPane1.setName("jScrollPane1"); // NOI18N

        labelPatientInfo.setText(resourceMap.getString("labelPatientInfo.text")); // NOI18N
        labelPatientInfo.setToolTipText(resourceMap.getString("labelPatientInfo.toolTipText")); // NOI18N
        labelPatientInfo.setVerticalAlignment(javax.swing.SwingConstants.TOP);
        labelPatientInfo.setName("labelPatientInfo"); // NOI18N
        jScrollPane1.setViewportView(labelPatientInfo);

        jPanel2.setBorder(new javax.swing.border.MatteBorder(null));
        jPanel2.setName("jPanel2"); // NOI18N

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(ru.apertum.diasled.Diasled.class).getContext().getActionMap(FVisitEditor.class, this);
        buttonSave.setAction(actionMap.get("saveVisit")); // NOI18N
        buttonSave.setName("buttonSave"); // NOI18N

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
                .addContainerGap(194, Short.MAX_VALUE)
                .addComponent(buttonSave)
                .addContainerGap())
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
                .addContainerGap(11, Short.MAX_VALUE)
                .addComponent(buttonSave)
                .addContainerGap())
        );

        jScrollPane2.setName("jScrollPane2"); // NOI18N

        tablePatientVisits.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {"1", "20.05.2004", "Общее направление"},
                {"2", "14.06.2004", "Повторное обследование"},
                {"3", "13.12.10", "Профилактика"},
                {null, null, null}
            },
            new String [] {
                "№", "Дата", "Описание"
            }
        ));
        tablePatientVisits.setName("tablePatientVisits"); // NOI18N
        tablePatientVisits.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        jScrollPane2.setViewportView(tablePatientVisits);
        tablePatientVisits.getColumnModel().getColumn(0).setPreferredWidth(15);
        tablePatientVisits.getColumnModel().getColumn(0).setHeaderValue(resourceMap.getString("tablePatientVisits.columnModel.title0")); // NOI18N
        tablePatientVisits.getColumnModel().getColumn(1).setHeaderValue(resourceMap.getString("tablePatientVisits.columnModel.title1")); // NOI18N
        tablePatientVisits.getColumnModel().getColumn(2).setHeaderValue(resourceMap.getString("tablePatientVisits.columnModel.title2")); // NOI18N

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 329, Short.MAX_VALUE)
                .addContainerGap())
            .addComponent(jPanel2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 349, Short.MAX_VALUE)
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 267, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 174, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        jSplitPane1.setRightComponent(jPanel1);

        jPanel3.setName("jPanel3"); // NOI18N

        jPanel4.setBorder(new javax.swing.border.MatteBorder(null));
        jPanel4.setName("jPanel4"); // NOI18N

        labelAgeOnDate.setText(resourceMap.getString("labelAgeOnDate.text")); // NOI18N
        labelAgeOnDate.setName("labelAgeOnDate"); // NOI18N

        spinnerWeightOnData.setModel(new javax.swing.SpinnerNumberModel(75, 3, 475, 1));
        spinnerWeightOnData.setName("spinnerWeightOnData"); // NOI18N

        jLabel3.setText(resourceMap.getString("jLabel3.text")); // NOI18N
        jLabel3.setName("jLabel3"); // NOI18N

        labelVisitDate.setFont(resourceMap.getFont("labelVisitDate.font")); // NOI18N
        labelVisitDate.setText(resourceMap.getString("labelVisitDate.text")); // NOI18N
        labelVisitDate.setName("labelVisitDate"); // NOI18N

        textFieldKod.setText(resourceMap.getString("textFieldKod.text")); // NOI18N
        textFieldKod.setName("textFieldKod"); // NOI18N

        jLabel5.setText(resourceMap.getString("jLabel5.text")); // NOI18N
        jLabel5.setName("jLabel5"); // NOI18N

        textFieldVisitDescription.setText(resourceMap.getString("textFieldVisitDescription.text")); // NOI18N
        textFieldVisitDescription.setName("textFieldVisitDescription"); // NOI18N

        jLabel6.setText(resourceMap.getString("jLabel6.text")); // NOI18N
        jLabel6.setName("jLabel6"); // NOI18N

        javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
        jPanel4.setLayout(jPanel4Layout);
        jPanel4Layout.setHorizontalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(labelVisitDate)
                    .addGroup(jPanel4Layout.createSequentialGroup()
                        .addComponent(labelAgeOnDate)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 167, Short.MAX_VALUE)
                        .addComponent(jLabel5)
                        .addGap(18, 18, 18)
                        .addComponent(textFieldKod, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(jPanel4Layout.createSequentialGroup()
                        .addComponent(jLabel3)
                        .addGap(18, 18, 18)
                        .addComponent(spinnerWeightOnData, javax.swing.GroupLayout.PREFERRED_SIZE, 56, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(jPanel4Layout.createSequentialGroup()
                        .addComponent(jLabel6)
                        .addGap(18, 18, 18)
                        .addComponent(textFieldVisitDescription, javax.swing.GroupLayout.DEFAULT_SIZE, 415, Short.MAX_VALUE)))
                .addContainerGap())
        );
        jPanel4Layout.setVerticalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(labelVisitDate)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(labelAgeOnDate)
                    .addComponent(textFieldKod, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel5))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel3)
                    .addComponent(spinnerWeightOnData, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(textFieldVisitDescription, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel6))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel5.setBorder(new javax.swing.border.MatteBorder(null));
        jPanel5.setName("jPanel5"); // NOI18N

        buttonNextVisit.setAction(actionMap.get("nextVisit")); // NOI18N
        buttonNextVisit.setName("buttonNextVisit"); // NOI18N

        buttonPreviousVisit.setAction(actionMap.get("previousVisit")); // NOI18N
        buttonPreviousVisit.setName("buttonPreviousVisit"); // NOI18N

        javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5);
        jPanel5.setLayout(jPanel5Layout);
        jPanel5Layout.setHorizontalGroup(
            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel5Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(buttonPreviousVisit)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 170, Short.MAX_VALUE)
                .addComponent(buttonNextVisit)
                .addContainerGap())
        );
        jPanel5Layout.setVerticalGroup(
            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel5Layout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(buttonNextVisit)
                    .addComponent(buttonPreviousVisit))
                .addContainerGap())
        );

        jTabbedPane1.setName("jTabbedPane1"); // NOI18N

        jPanel6.setName("jPanel6"); // NOI18N

        jSplitPane2.setDividerLocation(100);
        jSplitPane2.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        jSplitPane2.setContinuousLayout(true);
        jSplitPane2.setName("jSplitPane2"); // NOI18N

        jSplitPane3.setDividerLocation(90);
        jSplitPane3.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        jSplitPane3.setContinuousLayout(true);
        jSplitPane3.setName("jSplitPane3"); // NOI18N

        jScrollPane4.setName("jScrollPane4"); // NOI18N

        textAreaLeftLeg.setColumns(20);
        textAreaLeftLeg.setFont(resourceMap.getFont("textAreaLeftLeg.font")); // NOI18N
        textAreaLeftLeg.setRows(5);
        textAreaLeftLeg.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("textAreaLeftLeg.border.title"))); // NOI18N
        textAreaLeftLeg.setName("textAreaLeftLeg"); // NOI18N
        jScrollPane4.setViewportView(textAreaLeftLeg);

        jSplitPane3.setTopComponent(jScrollPane4);

        jScrollPane5.setName("jScrollPane5"); // NOI18N

        textAreaRightLeg.setColumns(20);
        textAreaRightLeg.setFont(resourceMap.getFont("textAreaRightLeg.font")); // NOI18N
        textAreaRightLeg.setRows(5);
        textAreaRightLeg.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("textAreaRightLeg.border.title"))); // NOI18N
        textAreaRightLeg.setName("textAreaRightLeg"); // NOI18N
        jScrollPane5.setViewportView(textAreaRightLeg);

        jSplitPane3.setRightComponent(jScrollPane5);

        jSplitPane2.setBottomComponent(jSplitPane3);

        jScrollPane3.setName("jScrollPane3"); // NOI18N

        textAreaCommonStatus.setColumns(20);
        textAreaCommonStatus.setFont(resourceMap.getFont("textAreaCommonStatus.font")); // NOI18N
        textAreaCommonStatus.setRows(5);
        textAreaCommonStatus.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("textAreaCommonStatus.border.title"))); // NOI18N
        textAreaCommonStatus.setName("textAreaCommonStatus"); // NOI18N
        jScrollPane3.setViewportView(textAreaCommonStatus);

        jSplitPane2.setLeftComponent(jScrollPane3);

        javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6);
        jPanel6.setLayout(jPanel6Layout);
        jPanel6Layout.setHorizontalGroup(
            jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 499, Short.MAX_VALUE)
        );
        jPanel6Layout.setVerticalGroup(
            jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 305, Short.MAX_VALUE)
        );

        jTabbedPane1.addTab(resourceMap.getString("jPanel6.TabConstraints.tabTitle"), jPanel6); // NOI18N

        jPanel7.setName("jPanel7"); // NOI18N

        jPanel8.setBorder(new javax.swing.border.MatteBorder(null));
        jPanel8.setName("jPanel8"); // NOI18N

        buttonAddExam.setAction(actionMap.get("createNewExam")); // NOI18N
        buttonAddExam.setName("buttonAddExam"); // NOI18N

        buttonRemoveExam.setAction(actionMap.get("removeExam")); // NOI18N
        buttonRemoveExam.setName("buttonRemoveExam"); // NOI18N

        jButton1.setAction(actionMap.get("showExam")); // NOI18N
        jButton1.setName("jButton1"); // NOI18N

        javax.swing.GroupLayout jPanel8Layout = new javax.swing.GroupLayout(jPanel8);
        jPanel8.setLayout(jPanel8Layout);
        jPanel8Layout.setHorizontalGroup(
            jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel8Layout.createSequentialGroup()
                .addContainerGap(60, Short.MAX_VALUE)
                .addComponent(buttonRemoveExam)
                .addGap(22, 22, 22)
                .addComponent(jButton1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(buttonAddExam)
                .addContainerGap())
        );
        jPanel8Layout.setVerticalGroup(
            jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel8Layout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(buttonAddExam)
                    .addComponent(buttonRemoveExam)
                    .addComponent(jButton1))
                .addContainerGap())
        );

        jScrollPane6.setName("jScrollPane6"); // NOI18N

        javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("root");
        javax.swing.tree.DefaultMutableTreeNode treeNode2 = new javax.swing.tree.DefaultMutableTreeNode("В типе обови 1");
        javax.swing.tree.DefaultMutableTreeNode treeNode3 = new javax.swing.tree.DefaultMutableTreeNode("Вкладки типа 1");
        javax.swing.tree.DefaultMutableTreeNode treeNode4 = new javax.swing.tree.DefaultMutableTreeNode("Стоя 11:45");
        treeNode3.add(treeNode4);
        treeNode4 = new javax.swing.tree.DefaultMutableTreeNode("Ходьба 13:45");
        treeNode3.add(treeNode4);
        treeNode4 = new javax.swing.tree.DefaultMutableTreeNode("Бег 12:13");
        treeNode3.add(treeNode4);
        treeNode2.add(treeNode3);
        treeNode3 = new javax.swing.tree.DefaultMutableTreeNode("Вкладки типа 2");
        treeNode4 = new javax.swing.tree.DefaultMutableTreeNode("Стоя 11:45");
        treeNode3.add(treeNode4);
        treeNode4 = new javax.swing.tree.DefaultMutableTreeNode("Ходьба 13:45");
        treeNode3.add(treeNode4);
        treeNode4 = new javax.swing.tree.DefaultMutableTreeNode("Бег 12:13");
        treeNode3.add(treeNode4);
        treeNode2.add(treeNode3);
        treeNode1.add(treeNode2);
        treeNode2 = new javax.swing.tree.DefaultMutableTreeNode("В типе обови 2");
        treeNode3 = new javax.swing.tree.DefaultMutableTreeNode("Вкладки типа 1");
        treeNode4 = new javax.swing.tree.DefaultMutableTreeNode("Стоя 11:45");
        treeNode3.add(treeNode4);
        treeNode4 = new javax.swing.tree.DefaultMutableTreeNode("Ходьба 13:45");
        treeNode3.add(treeNode4);
        treeNode4 = new javax.swing.tree.DefaultMutableTreeNode("Бег 12:13");
        treeNode3.add(treeNode4);
        treeNode2.add(treeNode3);
        treeNode3 = new javax.swing.tree.DefaultMutableTreeNode("Вкладки типа 2");
        treeNode4 = new javax.swing.tree.DefaultMutableTreeNode("Стоя 11:45");
        treeNode3.add(treeNode4);
        treeNode4 = new javax.swing.tree.DefaultMutableTreeNode("Ходьба 13:45");
        treeNode3.add(treeNode4);
        treeNode4 = new javax.swing.tree.DefaultMutableTreeNode("Бег 12:13");
        treeNode3.add(treeNode4);
        treeNode2.add(treeNode3);
        treeNode1.add(treeNode2);
        treeExams.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1));
        treeExams.setName("treeExams"); // NOI18N
        treeExams.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                treeExamsMouseClicked(evt);
            }
        });
        treeExams.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                treeExamsKeyTyped(evt);
            }
        });
        jScrollPane6.setViewportView(treeExams);

        javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7);
        jPanel7.setLayout(jPanel7Layout);
        jPanel7Layout.setHorizontalGroup(
            jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel8, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jScrollPane6, javax.swing.GroupLayout.DEFAULT_SIZE, 499, Short.MAX_VALUE)
        );
        jPanel7Layout.setVerticalGroup(
            jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel7Layout.createSequentialGroup()
                .addComponent(jScrollPane6, javax.swing.GroupLayout.DEFAULT_SIZE, 252, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel8, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        jTabbedPane1.addTab(resourceMap.getString("jPanel7.TabConstraints.tabTitle"), jPanel7); // NOI18N

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jTabbedPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 504, Short.MAX_VALUE)
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jTabbedPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 333, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        jSplitPane1.setLeftComponent(jPanel3);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 862, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 513, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        if (isChangedVisit() && JOptionPane.showConfirmDialog(this,
                "Данные по посещению были изменены. Сохранить изменения?",
                "Сохранение посещения",
                JOptionPane.YES_NO_OPTION) == 0) {
            saveVisit();
        }
    }//GEN-LAST:event_formWindowClosing

    private void treeExamsMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_treeExamsMouseClicked
        if (evt.getClickCount() > 1) {
            showExam();
        }
    }//GEN-LAST:event_treeExamsMouseClicked

    private void treeExamsKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_treeExamsKeyTyped
        if (evt.getKeyChar() == '\n') {
            showExam();
        }
    }//GEN-LAST:event_treeExamsKeyTyped

    @Action
    public void showVisit() {
    }

    @Action
    public void nextVisit() {
        final Visit v = getVisitCloseOf(visit, true);
        if (v != null) {
            showData(v);
            selectByVisit(v);
        }
    }

    @Action
    public void previousVisit() {
        final Visit v = getVisitCloseOf(visit, false);
        if (v != null) {
            showData(v);
            selectByVisit(v);
        }
    }

    private void selectByVisit(Visit v) {
        for (int i = 0; i < tablePatientVisits.getModel().getRowCount(); i++) {
            if (Uses.isSameDates((Date) tablePatientVisits.getModel().getValueAt(i, 1), v.getDate())) {
                tablePatientVisits.getSelectionModel().addSelectionInterval(i, i);
                break;
            }
        }
    }

    /**
     * Получить ближайший визит относительно какого-то визита
     * @param currentVisit относительно этого визита будет искаться ближайший визит
     * @param isNext true - следующий за, false - предыдущий за
     * @return ближайший визит, либо null если нет ближайшего в этом направлениии
     */
    private Visit getVisitCloseOf(Visit currentVisit, boolean isNext) {
        Visit res = null;
        for (Visit vis : currentVisit.getPatient().getVisits()) {
            if (vis.getId() == currentVisit.getId()) {
                continue;
            }
            boolean f = isNext ? vis.getDate().after(currentVisit.getDate()) : vis.getDate().before(currentVisit.getDate());
            if (f) {
                if (res == null) {
                    res = vis;
                } else {
                    f = isNext ? res.getDate().after(vis.getDate()) : res.getDate().before(vis.getDate());
                    if (f) {
                        res = vis;
                    }
                }
            }
        }
        return res;
    }

    @Action
    public void createNewExam() {
        final FExamMaster em = new FExamMaster(this, true, visit);
        em.setLocationRelativeTo(null);
        em.setVisible(true);
        if (em.result != null) {
            final TreeNode newExam = ((RootNodeExam) treeExams.getModel().getRoot()).addExam(em.result);
            ((ExamTree) treeExams.getModel()).reload();
            final TreeNode[] nodes = ((ExamTree) treeExams.getModel()).getPathToRoot(newExam);
            final TreePath path = new TreePath(nodes);
            treeExams.scrollPathToVisible(path);
            treeExams.setSelectionPath(path);

            FExamination.getInstance().setLocationRelativeTo(null);
            FExamination.getInstance().showExam(em.result);
        } else {
            JOptionPane.showMessageDialog(this,
                    "Обследование завершено НЕ успешно.",
                    "Завершение обследования",
                    JOptionPane.ERROR_MESSAGE);
        }
    }

    @Action
    public void removeExam() {
        final TreeNode node = (TreeNode) treeExams.getLastSelectedPathComponent();
        if (node != null && node.isLeaf() && JOptionPane.showConfirmDialog(this,
                "Обследование \"" + node.toString() + "\" будет удалено безвозвратно?",
                "Удаление обследования",
                JOptionPane.YES_NO_OPTION) == 0) {
            final ExamNode eNode = (ExamNode) node;
            Examination.removeExam(eNode.getExam());
            final TreeNode parentFolder = ((RootNodeExam) treeExams.getModel().getRoot()).removeExam(eNode.getExam());
            ((ExamTree) treeExams.getModel()).reload();
            final TreeNode[] nodes = ((ExamTree) treeExams.getModel()).getPathToRoot(parentFolder);
            final TreePath path = new TreePath(nodes);
            treeExams.scrollPathToVisible(path);
            treeExams.setSelectionPath(path);
            treeExams.expandPath(path);
        }
    }

    @Action
    public void showExam() {
        final TreeNode node = (TreeNode) treeExams.getLastSelectedPathComponent();
        if (node != null && node.isLeaf() && node.getParent() != null) {
            final ExamNode eNode = (ExamNode) node;
            FExamination.getInstance().setLocationRelativeTo(null);
            FExamination.getInstance().showExam(eNode.getExam());
        }
    }

    @Action
    public void saveVisit() {
        Uses.log.logger.info("Сохраняем посещение. " + visit.getDate());
        visit.setComments(textFieldVisitDescription.getText());
        visit.setKod(textFieldKod.getText());
        visit.setWeight((Integer) spinnerWeightOnData.getModel().getValue());
        visit.setCommonStatus(textAreaCommonStatus.getText());
        visit.setLeftLegInfo(textAreaLeftLeg.getText());
        visit.setRigthLegInfo(textAreaRightLeg.getText());
        try {
            Visit.saveVisit(visit);
        } catch (ClientException ex) {
            JOptionPane.showMessageDialog(this,
                    "Ошибка сохранения посещения.",
                    "Сохранение посещения",
                    JOptionPane.ERROR_MESSAGE);
            return;
        }
        JOptionPane.showMessageDialog(this,
                "Данные по посещению были успешно сохранены",
                "Сохранение посещения",
                JOptionPane.INFORMATION_MESSAGE);
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton buttonAddExam;
    private javax.swing.JButton buttonNextVisit;
    private javax.swing.JButton buttonPreviousVisit;
    private javax.swing.JButton buttonRemoveExam;
    private javax.swing.JButton buttonSave;
    private javax.swing.JButton jButton1;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JPanel jPanel5;
    private javax.swing.JPanel jPanel6;
    private javax.swing.JPanel jPanel7;
    private javax.swing.JPanel jPanel8;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JScrollPane jScrollPane4;
    private javax.swing.JScrollPane jScrollPane5;
    private javax.swing.JScrollPane jScrollPane6;
    private javax.swing.JSplitPane jSplitPane1;
    private javax.swing.JSplitPane jSplitPane2;
    private javax.swing.JSplitPane jSplitPane3;
    private javax.swing.JTabbedPane jTabbedPane1;
    private javax.swing.JLabel labelAgeOnDate;
    private javax.swing.JLabel labelPatientInfo;
    private javax.swing.JLabel labelVisitDate;
    private javax.swing.JSpinner spinnerWeightOnData;
    private javax.swing.JTable tablePatientVisits;
    private javax.swing.JTextArea textAreaCommonStatus;
    private javax.swing.JTextArea textAreaLeftLeg;
    private javax.swing.JTextArea textAreaRightLeg;
    private javax.swing.JTextField textFieldKod;
    private javax.swing.JTextField textFieldVisitDescription;
    private javax.swing.JTree treeExams;
    // End of variables declaration//GEN-END:variables
}
